<?php
/**
 * Created by PhpStorm.
 * User: dell
 * Date: 2018/7/27
 * Time: 17:08
 */

namespace wechat;
//微信操作基础类
class Wx
{

    public $message;

    /*
     * 创建构造函数，优先获得微信传进本服务器的数据
     */
    public function __construct()
    {
//        为变量：消息赋值为接收微信服务器的数据，进行全局调用
        $this->message = $this->parseAction();

    }

    /**
     * 2.2创建微信接口认证方法
     */
    public function valid()
    {
        // 2.3直接将valid.php中的提前写好的接入程序剪切过来即可

        //1.1 需求与微信服务器建立联系；
        //.1 当我们点击微信公众平台->基本配置 的 提交按钮时，
        //微信服务器将自动为我们发送4个字段以GET请求的形式到我们填写的服务器地址 微信服务器会；
        //signature微信加密签名 timestamp时间戳
        // nonce随机数
        //echostr随机字符串
        //所以首先我们要先接收者4个字段的值
        $signature = $_GET['signature'];
        $timestamp = $_GET['timestamp'];
        $nonce = $_GET['nonce'];
        $echostr = $_GET['echostr'];

        //1.2 看到页面上的开发者token值得输入框了吗？现在我们在这里设置token值；
        $token = 'liutongToken';
        //1.3 根据开发者文档的第二步1）的需求;将token、timestamp、nonce三个参数进行字典序排序;
        //.1 将token、timestamp、nonce参数放入一个数组中;
        $arr = [$token, $timestamp, $nonce];
        //.2 根据需求对arr数组利用系统自带的sort()和SORT_STRING进行字典排序；
        sort($arr, SORT_STRING);
        //.3 根据手册第二步->2）的需求将上面排序好的数组进行数组分割，再字分割好的字符串拼接成一个字符串进行sha1加密
        //执行数组分割成字符串；
        $str = implode($arr);
        //将数组进行加密
        $string = sha1($str);
        //1.4 根据微信开发文档接入入口->第二步->3）开发者获得加密后的字符串可与signature对比，标识该请求来源于微信
        //.1 进行if判断，判断我们加密好的字符串和微信服务器给我们发来的加密字符串是否一致
        if ($string == $signature) {
            //如果两次加密后的签名相同,代表所有参数都相同,加密方式一样,这个时候,我们需要将微信给我们的$echostr参数原样输出给它
            echo $echostr;
        }
    }
//    2.3上面的微信接口接入方法已经接入完成
//     现在返回index进行调用

//3.2 创建获得用户提交数据的方法；注意:想要获得用户提交过来的数据，就必须先要的到微信服务器为我们发来的信息；所以在下方建立一个获得微信服务器向我们发信息的方法；
    public function getMessage()
    {
//        调用微信传进来本服务器的数据。将这个数据返回给调用他的地方；
        return $this->message;
        //现在去Entry中操作，测试用户发来的消息；
    }

//3.3创建接收微信服务器向我们发送数据的方法
    public function parseAction()
    {
//    获取服务器上数据流的数据，file_get_contents()将整个文件读入一个字符串；
//    参数1;要读取的文件
        $xml = file_get_contents('php://input');
//    判断是否接到了数据，如果有数据就对数据进行处理；
        if ($xml) {
//        将$xml数据转换成对象
//            使用自带方法simplexml_load_string();
//        参数1：要处理的数据是什么；
//        参数2：是你要转换成的对象的名称,名称就是方法的第二个参数；
            $message = simplexml_load_string($xml, 'simpleXMLElement', LIBXML_NOCDATA);
            return $message;
//            写完方法到构造函数去调用
        }

    }

    /**
     *
     * curl发送请求方法
     *
     * @param $url  请求地址
     * @param array $field 提交的数据
     * @return string
     */
    public function curl($url, $field = [])
    {
        //初始化curl
        $ch = curl_init();
        //设置curl参数
        //设置请求地址
        curl_setopt($ch, CURLOPT_URL, $url);
        //设置接收返回结果,但不直接展示在界面
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        //设置禁止证书校验
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        //判断是否为post请求
        if (!empty($field)) {
            //定义超时时间
            curl_setopt($ch, CURLOPT_TIMEOUT, 30);
            //开启post请求
            curl_setopt($ch, CURLOPT_POST, 1);
            //传递post数据
            curl_setopt($ch, CURLOPT_POSTFIELDS, $field);
        }

        //发送请求,定义一个变量接收请求结果
        $data = '';
        //发送请求可能失败,所以我需要判断,如果请求成功,将请求结果赋值给$data,反之,不给$data赋值
        if (curl_exec($ch)) {
            $data = curl_multi_getcontent($ch);
        }
        //关闭curl
        curl_close($ch);
        //返回接收到的数据
        return $data;
    }

//    8.2创建getAccessToken()方法

    /**
     *
     * 1.首先定义请求地址和确定请求方式,向微信端发送获取access_token的请求,会获取到对应的值
     * 2.如果每次都请求,2个小时有效期浪费,我们应该将数据保存到文件中
     * 3.定义保存的目录和文件名称,
     * 4.每次调用方法的时候,首先判断是否存在存放access_token缓存数据的文件,并且该文件是否过期,如果存在并且没过期,直接取值,如果不存在或者过期了,重新获取,然后重新保存
     * 5.最后将access_token的值返回出去
     */
    public function getAccessToken()
    {
//            创建一个文件，将access_token文件存在我们指定的文件中 __DIR__ 是当前目录
        $dir = __DIR__ . '/cache';
//            使用短路写法创建文件夹
        //判定是否存在这个目录 存在就存在 不存在就创建一个出来
        is_dir($dir) || mkdir($dir);
        //定义文件的名称 进行一个字符创的拼接  md5('随便写的')怕文件名重复；
        $filename = $dir . '/token_' . md5('daasdsadasd') . '.php';
        //每次调用这个方法 时，就应该判定这个文件是否存在，并且判断文件最后一次修改的时间+7100秒后是否发大于当前的2小时。大于了就说明保存的文件已经过期需要重新获取。
        if (is_file($filename) && filemtime($filename) + 7100 > time()) {
//            获取$filename文件的数据；
            $data = include $filename;
        } else {
            //appid和secret在测试号一上来就是
            $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx051616c0a941e4a3&secret=49dd27d027f5e6edab8a0bb44b87ff8f';
            //使用curl方法发送get请求,获取access_token
            $data = $this->curl($url);
//        将经过处理的返回结果进行处理，判定返回的结果是否有错，有错就处理，没错就存起来。然后将json格式转换为php能读懂的数组
            $data = json_decode($data, true);
//            print_r($data);
//        进行错误检测
            if (isset($data['errcode'])) {
                return false;
            }
//        否则将得到的正常数据写入文件夹
//        创建文件夹  将￥data利用var_export($data,true)方法 变成字符串
//        将这个字符串存入这$filename这个文件中，在将这个文件变为一个字符串；
//            print_r($filename);die;
            file_put_contents($filename, "<?php return " . var_export($data, true) . ";\n?>");

        }
        //最终将access_token的值返回
        return $data['access_token'];
        //现在反回Entry操作8.2
    }

    /**
     * getJsApiTicket权限签名算法
     * 没有这个算法将导致无法使用分享功能
     * 手册微信网页开发->微信JS-SDK说明文档->附录1-JS-SDK使用权限签名算法
     * 因测试时使用次数限制，将它保存在本地，使用2小时最大时间后进行跟换一次
     */
    public function getJsApiTicket(){
//        创建本地文件夹，将文件保存至本地
        $dir = __DIR__ . '/cache';
//        使用短路写法创建文件目录
        //检测目录是否存在。不存在则创建一个出来
        is_dir($dir)||mkdir($dir);
//        创建文件 使用md5是为了放置每次创建出来的文件名重复
        $filename = $dir . '/ticket_'.md5('aaa123aaa').'.php';
//        $dd = $this->getAccessToken();
//        print_r($dd);
//        die;
        //判定签名文件是否存在并且是创建时间是否大于2小时，如果文件存在，且最后修改时间小于2小时则直接从这个文件中取值，若有一个条件不满足则向微信服务器请求，并接受返回的数据，将返回数据写入文件夹
//       var_dump($filename);
        if(is_file($filename) && filemtime($filename) +7100 >time()){
            $data = include $filename;
        }else{
            $url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token='.$this->getAccessToken().'&type=jsapi';
            $data = $this->curl($url);
//                var_dump($data);
            $data = json_decode($data,true);
//            var_dump($data);
            if ($data['errcode'] != 0){
                return false;
            }else{
                file_put_contents($filename,'<?php return '.var_export($data,true).";\n?>");
            }
        }
        return $data['ticket'];
    }

}